import turbogears   as tg
from turbogears import config
import logging
import cherrypy
import model

from datetime import date, datetime, timedelta
from model                   import Action, Tag, Project, Context, Note, Priority, Property, session
from turbogears              import controllers, expose, validate, validators, redirect, error_handler, flash, widgets, view
import turbolucene
from turbolucene import *
from turbogears.feed import FeedController
from docutils.core import publish_parts
import re
from sqlalchemy              import and_, or_, asc
from formencode              import validators
from subcontrollers.project  import ProjectController
from subcontrollers.action   import ActionController
from subcontrollers.tag      import TagController
#from subcontrollers.feed     import FeedController
from subcontrollers.context  import ContextController
from subcontrollers.sandbox  import SandboxController
from subcontrollers.note     import NoteController
from subcontrollers.property import PropertyController
from subcontrollers.review import ReviewController

log = logging.getLogger("kaizen.model")

def make_document(project):
    """Turn project into a TurboLucene document."""
    document = Document()
    document.add(Field('id', str(project.id), STORE, UN_TOKENIZED))
    document.add(Field('title', project.title, STORE, UN_TOKENIZED))
    document.add(Field('notes', project.notes, COMPRESS, TOKENIZED))
    return document

def results_formatter(results):
    """Return the projects that match the ids provided by TurboLucene"""
    if results:
        return session.query(Project).select(Project.c.id.in_(*results))

indexing = cherrypy.config.get('indexing.on','False')
if(indexing == 'True'):
    log.info('indexing is on')
    print('indexing is on')
    turbolucene.start(make_document, ['notes'], results_formatter)

class NotesProvider(object):

    def __init__(self):
        pass

    def update(self, *args, **kw):
        self.data = session.query(Note).select()
        self.last_update = datetime.now()

    def __repr__(self):
        return self.data

class ContextProvider(object):

    def __init__(self):
        pass

    def update(self, *args, **kw):
        self.data = session.query(Context).select()
        self.last_update = datetime.now()

    def __repr__(self):
        return self.data

class ProjectProvider(object):

    def __init__(self):
        pass

    def update(self, *args, **kw):
        self.data = session.query(Project).select(Project.c.closed==0)
        self.last_update = datetime.now()
    def __repr__(self):
        return self.data

class ClosedProjectProvider(object):

    def __init__(self):
        pass

    def update(self, *args, **kw):
        self.data = session.query(Project).select(Project.c.closed==1)
        self.last_update = datetime.now()
    def __repr__(self):
        return self.data

class NextActionProvider(object):

    def __init__(self):
        pass

    def update(self, *args, **kw):
        self.last_update = datetime.now()
        self.data = session.query(Action).select(and_(Action.c.priority==0, Action.c.closed==False))

    def __repr__(self):
        return self.data

class PropertyProvider(object):
    def __init__(self):
        pass

    def update(self, *args, **kw):
        self.last_update = datetime.now()
        calendarUrl = session.query(Property).select(Property.c.key=='calendarUrl')
        if len(calendarUrl) == 0:
          calendarUrl = Property(key='calendarUrl', value='')
          calendarUrl.flush()
        else:
          calendarUrl = calendarUrl[0]
        self.calendarUrl = calendarUrl.value
        self.data = {'calendarUrl': calendarUrl} #all properties

    def __repr__(self):
        return self.data

class HistoryProvider(object):
    def __init__(self):
        pass

    def update(self, *args, **kw):
        today = date.today()
        two_weeks = timedelta(days=-14)
        two_weeks_time = today + two_weeks

        self.last_update = datetime.now()
        notes = session.query(Note).select()
        for item in notes:
            item.type = 3
        actions = session.query(Action).select(Action.c.modified > two_weeks_time.strftime("%Y-%m-%d %H:%M:%S"),order_by=[asc(Action.c.modified)])
        for item in actions:
            item.type = 2
        projects = session.query(Project).select(Project.c.modified > two_weeks_time.strftime("%Y-%m-%d %H:%M:%S"),order_by=[asc(Project.c.modified)])
        for item in projects:
            item.type = 1
        history = projects + actions + notes
        history.sort( lambda a,b: cmp( (str(b.modified)), (str(a.modified)) ) )
        self.data = history[:15]

    def __repr__(self):
        return self.data

note_provider = NotesProvider()
context_provider = ContextProvider()
project_provider = ProjectProvider()
closed_project_provider = ClosedProjectProvider()
next_action_provider = NextActionProvider()
history_provider = HistoryProvider()
property_provider = PropertyProvider()
wikiwords = re.compile(r"\b([A-Z]\w+[A-Z]+\w+)")


allOpenProjects = session.query(Project).select(Project.c.closed==0)

def reload():
  note_provider.update()
  context_provider.update()
  project_provider.update()
  closed_project_provider.update()
  next_action_provider.update()
  history_provider.update()
  property_provider.update()

def init_providers(vars):
  log.debug("--------init--------")

  priorityNext = Priority()
  priorityNext.title='next'
  priorityNext.value=0
  prioritySecond = Priority()
  prioritySecond.title='none'
  prioritySecond.value=1

  note_provider.update()
  context_provider.update()
  project_provider.update()
  closed_project_provider.update()
  next_action_provider.update()
  history_provider.update()
  property_provider.update()

  vars["contexts"] = context_provider.data
  vars["projects"] = project_provider.data
  vars["closedProjects"] = closed_project_provider.data
  vars["notes"] = note_provider.data
  vars["history"] = history_provider.data
  vars["nextActions"] = next_action_provider.data
  vars["priorities"] = [priorityNext, prioritySecond]
  vars["prop_calendarUrl"] = property_provider.calendarUrl
  vars["props"] = property_provider.data

view.variable_providers.append(init_providers)

class Root(controllers.RootController):
    log.debug("---Root---")

    project = ProjectController()
    action = ActionController()
    context = ContextController()
    tag = TagController()
    note = NoteController()
    property = PropertyController()
    review = ReviewController()
    #feed = Feed()

    sandbox = SandboxController()

    @expose(template="kaizen.templates.welcome", content_type='text/html; charset=utf-8')
    def index(self):
        return dict(previousPage='kaizen.templates.welcome')

    @expose(content_type='text/html; charset=utf-8')
    def forward(self, template):
        return dict(tg_template=str(template))

    def refresh(self):
        reload();

    @expose(template="kaizen.templates.search", content_type='text/html; charset=utf-8')
    @error_handler()
    def search(self, query, **keywords):
        log.debug("search Projects. Query: " +query +".")
        results = turbolucene.search(query)
        tg.flash("searched")
        log.debug("searched Projects. Result size :" +str(results) +".")
        return dict(results=results, query=query)





